package com.voda.web.controller;

import java.util.List;
import java.util.Map;

import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.mail.MailSendException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.voda.entity.Role;
import com.voda.entity.User;
import com.voda.errors.NotMatchPasswordException;
import com.voda.service.api.IRoleService;
import com.voda.service.api.IUserService;
import com.voda.web.common.AbstractMappingController;
import com.voda.web.util.ResponseMapUtil;

/**
 * The Class UserController.
 */
@Controller
@RequestMapping(value="/cms/users")
public class UserController extends AbstractMappingController {
	
	/** The Constant PROPERTY_OLD_PASSWORD. */
	private static final String PROPERTY_OLD_PASSWORD = "oldPassword";

	/** The Constant GET_BY_ID_URL. */
	private static final String GET_BY_ID_URL = "/get";
	
	/** The Constant UPDATE_URL. */
	private static final String UPDATE_URL = "/update";

	/** The Constant SAVE_URL. */
	private static final String SAVE_URL = "/save";
	
	/** The Constant SAVE_URL. */
	private static final String RESET_PASSWORD_BY_ADMIN_URL = "/reset_password_by_admin";
	
	/** The Constant FORGOT_PASSWORD. */
	private static final String FORGOT_PASSWORD = "/forgot_password";
	
	/** The Constant SAVE_URL. */
	private static final String RESET_PASSWORD_BY_USER_URL = "/reset_password_by_user";
		
	/** The Constant PROPERTY_ID. */
	private static final String PROPERTY_ID = "id";
	
	/** The Constant PROPERTY_EMAIL. */
	private static final String PROPERTY_EMAIL = "email";
	
	/** The Constant PROPERTY_PASSWORD. */
	private static final String PROPERTY_PASSWORD = "password";
	
	/** The Constant PROPERTY_ID_ROLE. */
	private static final String PROPERTY_ID_ROLE = "roleId";	
	
	/** The Constant ERROR_GET_USER. */
	private static final String ERROR_GET_USER = "error";
	
	/** The Constant ERROR_GET_USERS. */
	private static final String ERROR_GET_USERS = "error";
	
	/** The Constant ERROR_UPDATE_USER. */
	private static final String ERROR_UPDATE_USER = "error";
	
	/** The Constant ERROR_ADD_USER. */
	private static final String ERROR_ADD_USER = "error";
	
	/** The Constant ERROR_ADD_USER_NOT_UNIQUE. */
	private static final String ERROR_ADD_USER_NOT_UNIQUE = "error";
	
	/** The Constant ERROR_USER_RESET_PASSWORD. */
	private static final String ERROR_USER_RESET_PASSWORD = "error";
	
	/** The Constant ERROR_USER_INCORRECT_PASSWORD. */
	private static final String ERROR_USER_INCORRECT_PASSWORD = "error";
	
	/** The Constant ERROR_SEND_MAIL_ADD_USER. */
	private static final String ERROR_SEND_MAIL_ADD_USER = "error";
	
	/** The Constant ERROR_SEND_MAIL_RESET_PASSWORD. */
	private static final String ERROR_SEND_MAIL_RESET_PASSWORD = "error";
	
	/** The Constant SUCCESS_GET_USER. */
	private static final String SUCCESS_GET_USER = "success";
	
	/** The Constant SUCCESS_GET_USERS. */
	private static final String SUCCESS_GET_USERS = "success";
	
	/** The Constant SUCCESS_UPDATE_USER. */
	private static final String SUCCESS_UPDATE_USER = "success";
	
	/** The Constant SUCCESS_ADD_USER. */
	private static final String SUCCESS_ADD_USER = "success";
	
	/** The Constant SUCCESS_USER_RESET_PASSWORD. */
	private static final String SUCCESS_USER_RESET_PASSWORD = "success";
	
	/** The user service. */
	@Autowired
	private IUserService userService;
	
	/** The role service. */
	@Autowired
	private IRoleService roleService;
	
	/** The context. */
	@Autowired
	private ApplicationContext context;
	
	/**
	 * Gets the users list.
	 *
	 * @return the users list
	 */
	@RequestMapping(method = RequestMethod.GET)
	public @ResponseBody Map<Object, Object> getUsersList() {
		try {
			List<User> result = userService.getAll();
			return ResponseMapUtil.mapSuccess(result, resourceBundleUtil.getMessage(SUCCESS_GET_USERS));
		} catch (Exception e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_GET_USERS));
		}
	}
	
	/**
	 * Gets the user by id.
	 *
	 * @param id the id
	 * @return the user by id
	 */
	@RequestMapping(value = GET_BY_ID_URL, method = RequestMethod.GET)
	public @ResponseBody Map<Object, Object> getUserById(@RequestParam Long id) {
		try {
			User result = userService.getUserWithRole(id);
			return ResponseMapUtil.mapSuccess(result, resourceBundleUtil.getMessage(SUCCESS_GET_USER));
		} catch (Exception e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_GET_USER));
		}
	}
	

	/**
	 * Update user.
	 *
	 * @param data the data
	 * @return the map
	 */
	@RequestMapping(value=UPDATE_URL, method = RequestMethod.PUT)
	public @ResponseBody Map<Object, Object> updateUser(@RequestBody Object data) {
		try {
			User user = (User) generateBaseEntityFromJson(data, User.class);
			userService.updateRecord(user);
			return ResponseMapUtil.mapSuccess(resourceBundleUtil.getMessage(SUCCESS_UPDATE_USER));
		} catch (Exception e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_UPDATE_USER));
		}
	}
	
	/**
	 * Save user.
	 *
	 * @param data the data
	 * @return the map
	 */
	@RequestMapping(value=SAVE_URL, method = RequestMethod.POST)
	public @ResponseBody Map<Object, Object> saveUser(@RequestBody Object data) {
		try {
			JSONObject jsonObject = JSONObject.fromObject(data);
			if (!userService.checkUnique(jsonObject.getString(PROPERTY_EMAIL))){
				return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_ADD_USER_NOT_UNIQUE));
			}
			Role role = roleService.getRecordById(jsonObject.getLong(PROPERTY_ID_ROLE));
			User user = new User();
			user.setEmail(jsonObject.getString(PROPERTY_EMAIL));
			user.setBlocked(false);
			user.setRole(role);
			userService.addRecord(user);
			return ResponseMapUtil.mapSuccess(resourceBundleUtil.getMessage(SUCCESS_ADD_USER));
		} catch (MailSendException e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_SEND_MAIL_ADD_USER));
		} catch (Exception e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_ADD_USER));
		}
	}
	
	/**
	 * Reset password by admin.
	 *
	 * @param data the data
	 * @return the map
	 */
	@RequestMapping(value=RESET_PASSWORD_BY_ADMIN_URL, method = RequestMethod.PUT)
	public @ResponseBody Map<Object, Object> resetPasswordByAdmin(@RequestBody Object data) {
		try {
			JSONObject jsonObject = JSONObject.fromObject(data);
			Long userId = jsonObject.getLong(PROPERTY_ID);
			User user = userService.getRecordById(userId);
			userService.resetPasswordByAdmin(user);		
			return ResponseMapUtil.mapSuccess(resourceBundleUtil.getMessage(SUCCESS_USER_RESET_PASSWORD));
		} catch (MailSendException e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_SEND_MAIL_RESET_PASSWORD));
		} catch (Exception e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_USER_RESET_PASSWORD));
		}
	}
	
	/**
	 * Reset password.
	 *
	 * @param data the data
	 * @return the map
	 */
	@RequestMapping(value=FORGOT_PASSWORD, method = RequestMethod.PUT)
	public @ResponseBody Map<Object, Object> resetPassword(@RequestBody Object data) {
		try {
			JSONObject jsonObject = JSONObject.fromObject(data);
			String userEmail = jsonObject.getString(PROPERTY_EMAIL);
			User user = userService.getUserByEmail(userEmail);
			userService.resetPasswordByAdmin(user);		
			return ResponseMapUtil.mapSuccess(resourceBundleUtil.getMessage(SUCCESS_USER_RESET_PASSWORD));
		} catch (MailSendException e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_SEND_MAIL_RESET_PASSWORD));
		} catch (Exception e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_USER_RESET_PASSWORD));
		}
	}
	
	/**
	 * Reset password by user.
	 *
	 * @param data the data
	 * @return the map
	 */
	@RequestMapping(value=RESET_PASSWORD_BY_USER_URL, method = RequestMethod.PUT)
	public @ResponseBody Map<Object, Object> resetPasswordByUser(@RequestBody Object data) {
		try {
			JSONObject jsonObject = JSONObject.fromObject(data);
			Long userId = jsonObject.getLong(PROPERTY_ID);
			String newPassword = jsonObject.getString(PROPERTY_PASSWORD);
			String oldPassword = jsonObject.getString(PROPERTY_OLD_PASSWORD);
			userService.resetPasswordByUser(userId, oldPassword, newPassword);
			return ResponseMapUtil.mapSuccess(resourceBundleUtil.getMessage(SUCCESS_USER_RESET_PASSWORD));
		} catch (NotMatchPasswordException e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_USER_INCORRECT_PASSWORD));
		} catch (MailSendException e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_SEND_MAIL_RESET_PASSWORD));
		} catch (Exception e) {
			return ResponseMapUtil.mapError(resourceBundleUtil.getMessage(ERROR_USER_RESET_PASSWORD));
		}
	}
	

}
